package com.hmall.search.controller;


import cn.hutool.core.bean.BeanUtil;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.query_dsl.*;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.json.JsonData;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hmall.api.item.dto.ItemDTO;
import com.hmall.common.domain.PageDTO;
import com.hmall.search.domain.po.Item;
import com.hmall.search.domain.po.ItemDoc;
import com.hmall.search.domain.query.ItemPageQuery;
import com.hmall.search.service.SearchService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

@Api(tags = "搜索相关接口")
@RestController
@RequestMapping("/search")
@RequiredArgsConstructor
public class SearchController {

    // private final IItemService itemService;
    private final ElasticsearchClient esClient;

    @ApiOperation("搜索商品")
    @GetMapping("/list")
    public PageDTO<ItemDTO> search(ItemPageQuery query) throws IOException {
        // 创建 bool 查询构造器
        BoolQuery.Builder boolBuilder = new BoolQuery.Builder();

        // must: name 匹配
        if (StringUtils.isNotBlank(query.getKey())) {
            MatchQuery matchQuery = MatchQuery.of(b -> b
                    .field("name")
                    .query(query.getKey())
            );
            boolBuilder.must(Query.of(q -> q.match(matchQuery)));
        }

        // filter: brand
        if (StringUtils.isNotBlank(query.getBrand())) {
            TermQuery termQuery = TermQuery.of(b -> b
                    .field("brand")
                    .value(query.getBrand())
            );
            boolBuilder.filter(Query.of(q -> q.term(termQuery)));
        }

        // filter: category
        if (StringUtils.isNotBlank(query.getCategory())) {
            TermQuery termQuery = TermQuery.of(b -> b
                    .field("category")
                    .value(query.getCategory())
            );
            boolBuilder.filter(Query.of(q -> q.term(termQuery)));
        }

        // price 范围查询
        if (query.getMinPrice() != null || query.getMaxPrice() != null) {
            RangeQuery.Builder rangeBuilder = new RangeQuery.Builder().field("price");
            if (query.getMinPrice() != null) {
                rangeBuilder.gte(JsonData.of(query.getMinPrice()));
            }
            if (query.getMaxPrice() != null) {
                rangeBuilder.lte(JsonData.of(query.getMaxPrice()));
            }
            RangeQuery rangeQuery = rangeBuilder.build();
            boolBuilder.filter(Query.of(q -> q.range(rangeQuery)));
        }

//         // 1. 构建高亮字段配置
//         HighlightField nameHighlight = HighlightField.of(b -> b
//                 .preTags("<em>")
//                 .postTags("</em>")
//                 .numberOfFragments(1)
//                 .fragmentSize(50)
//                 // .type(HighlightType.Unified)
//         );
//
// // 2. 构建 highlight 请求参数
//         HighlightField highlight = HighlightField.of(b -> b
//                 .putFields("name", nameHighlight)
//         );

        // 构建最终请求
        SearchRequest request = SearchRequest.of(b -> b
                .index("items")
                .trackTotalHits(t -> t.enabled(true))
                .from((query.getPageNo() - 1) * query.getPageSize())
                .size(query.getPageSize())
                .sort(st -> st.field(f -> f.field("updateTime").order(SortOrder.Desc)))
                .query(Query.of(q -> q.bool(boolBuilder.build())))
                .highlight(h->h.fields("name",x->x.preTags("<em>").postTags("</em>"))) // 添加高亮配置
        );

        // 执行搜索
        SearchResponse<ItemDoc> response = esClient.search(request, ItemDoc.class);

        // 处理响应结果
        Page<Item> result = new Page<>();
        long total = response.hits().total().value();
        result.setTotal(total);
        double ceil = Math.ceil(total / query.getPageSize());
        int pageNumTotal = (int) ceil;
        result.setPages(pageNumTotal);

        List<Item> items = response.hits().hits().stream().map(hit -> {
            ItemDoc itemDoc = hit.source();
            Item item = BeanUtil.toBean(itemDoc, Item.class);

            // 获取高亮结果（如果有）
            if (hit.highlight() != null && hit.highlight().containsKey("name")) {
                List<String> highlights = hit.highlight().get("name");
                if (!highlights.isEmpty()) {
                    item.setName(highlights.get(0)); // 使用第一个高亮片段替换原字段
                }
            }

            return item;
        }).collect(Collectors.toList());

        result.setRecords(items);

        // 封装并返回
        return PageDTO.of(result, ItemDTO.class);

    }

    private final SearchService searchService;

    @ApiOperation("自动补全")
    @GetMapping("/suggestion")
    public List<String> autoSuggestion(@RequestParam("key") String key){

        return searchService.autoSuggestion(key);
    }
}
// .query(q->q.match(m->
//         m.field("name").query(query.getKey()))
// ).query(q->q.term(t->
//         t.field("brand").value(query.getBrand()))
// ).query(q->q.term(t->
//         t.field("category").value(query.getCategory()))
// ).query(q->q.term(t->
//         t.field("status").value(1))
// ).query(q->q.range(r->
//         r.field("price")
//                 .gte(JsonData.of(query.getMinPrice()))
//                 .lte(JsonData.of(query.getMaxPrice())))
// )// 分页查询
//         // Page<Item> result = itemService.lambdaQuery()
//         //         .like(StrUtil.isNotBlank(query.getKey()), Item::getName, query.getKey())
//         //         .eq(StrUtil.isNotBlank(query.getBrand()), Item::getBrand, query.getBrand())
//         //         .eq(StrUtil.isNotBlank(query.getCategory()), Item::getCategory, query.getCategory())
//         //         .eq(Item::getStatus, 1)
//         //         .between(query.getMaxPrice() != null, Item::getPrice, query.getMinPrice(), query.getMaxPrice())
//         //         .page(query.toMpPage("update_time", false));